package com.task.core.service.impl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import com.task.common.constant.ErrorCodeConstants;
import com.task.common.utils.SecurityUtils;
import com.task.core.domain.DataScriptTypeInfo;
import com.task.core.dto.request.SysFilesRequestDTO;
import com.task.core.service.DataScriptTypeService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.PageHelper;
import com.task.common.exception.ServiceException;
import com.task.common.handler.Handler;
import com.task.common.utils.date.DateUtil;
import com.task.common.utils.file.FileUtils;
import com.task.core.domain.SysFileInfo;
import com.task.core.domain.SystemSettingInfo;
import com.task.core.dto.request.SysFileRequestDTO;
import com.task.core.dto.request.SysSettingRequestDTO;
import com.task.core.mapper.SysFileMapper;
import com.task.core.service.SysFileService;
import com.task.core.service.SysSettingService;

/**
 * @author 迪迦.
 * @date 2024/9/14 14:12
 */
@Service
public class SysFileServiceImpl implements SysFileService {

  @Resource
  private Environment environment;

  //public final static String FILE_PATH = isWindows() ? "D://testFileUpload//" : "/usr/local/fileUploadTask/";

  //public static boolean isWindows() {
  //  return System.getProperty("os.name").toLowerCase().contains(OsName.WINDOWS);
  //}
  //
  //public static boolean isLinux() {
  //  return System.getProperty("os.name").toLowerCase().contains(OsName.LINUX);
  //}

  @Resource
  private SysFileMapper sysFileMapper;

  @Resource
  private DataScriptTypeService dataScriptTypeService;

  @Resource
  private SysSettingService sysSettingService;


  public static void saveFile(String uploadDir, String fileName, MultipartFile multipartFile)
      throws IOException {
    // 确保目录存在
    File uploadDirectory = new File(uploadDir);
    if (!uploadDirectory.exists()) {
      uploadDirectory.mkdirs(); // 或者使用 mkdirs 创建多级目录
    }

    // 完整的保存路径
    File destinationFile = new File(uploadDir + File.separator + fileName);

    // 保存文件
    multipartFile.transferTo(destinationFile);
  }

  @Override
  public SysFileInfo upload(SysFileRequestDTO request, Long userid)
      throws IOException {
    MultipartFile file = request.getFile();
    if (null == file || file.isEmpty()) {
      throw new ServiceException("上传的文件对象不存在...");
    }
    long size = file.getSize();
    String contentType = file.getContentType();
    String fileName = file.getOriginalFilename();
    if (StringUtils.isEmpty(fileName)) {
      fileName = "newFile";
    }
    String[] split = fileName.split("\\.");
    String suffix = split.length > 1 ? split[split.length - 1] : "";
    String realName =
        UUID.randomUUID().toString().replace("-", "") + (StringUtils.isEmpty(suffix) ? ""
            : "." + suffix);
    //上传文件
    String time = DateUtil.dateToStr(new Date(), "yyyy/MM/dd/");
    String filePath = environment.getProperty("holatask.filePath");
    String source = filePath + time + realName;
    saveFile(filePath + time, realName, file);
    String url = "url";
    String code =
        StringUtils.isEmpty(request.getCode()) ? UUID.randomUUID().toString().replace("-", "")
            : request.getCode();
    SysFileInfo fileInfo = new SysFileInfo(code,
        fileName, url, source, size, realName, suffix, contentType, request.getFromCode(), null);
    sysFileMapper.addFile(fileInfo, userid);

    return fileInfo;
  }

  @Override
  public SysFileInfo uploadScript(SysFileRequestDTO request, Long userid) throws IOException, URISyntaxException, NoSuchAlgorithmException {
    MultipartFile file = request.getFile();
    if (null == file || file.isEmpty()) {
      throw new ServiceException("上传的文件对象不存在...");
    }
    SystemSettingInfo settingByTypeAndKey = sysSettingService.getSettingByTypeAndKey(new SysSettingRequestDTO("UPLOAD", "SCRIPT_FILE_SUFFIX"));
    if (ObjectUtils.isEmpty(settingByTypeAndKey) || com.task.common.utils.StringUtils.isEmpty(settingByTypeAndKey.getValue())) {
      throw new ServiceException("未配置脚本上传后缀");
    }
    List<String> sufs = Arrays.asList(settingByTypeAndKey.getValue().split(","));
    if (CollectionUtils.isEmpty(sufs)) {
      throw new ServiceException("未配置脚本上传后缀");
    }
    sufs = sufs.stream().map(String::toLowerCase).collect(Collectors.toList());
    long size = file.getSize();
    String contentType = file.getContentType();
    String fileName = file.getOriginalFilename();
    if (StringUtils.isEmpty(fileName)) {
      fileName = "newFile";
    }
    String[] split = fileName.split("\\.");
    String suffix = split.length > 1 ? split[split.length - 1] : "";
    suffix = suffix.toLowerCase();
    if (!sufs.contains(suffix)) {
      throw new ServiceException("不支持的文件格式,需要" + sufs);
    }
    String md5 = FileUtils.calculateHash(file, "MD5");
    String realName =
        UUID.randomUUID().toString().replace("-", "") + (StringUtils.isEmpty(suffix) ? "" : "." + suffix);
    //上传文件
    Handler handler = new Handler();
    String source = handler.uploadFile(file, realName);
    String url = environment.getProperty("holatask.awsS3Url") + source;
    String code = UUID.randomUUID().toString().replace("-", "");
    SysFileInfo fileInfo = new SysFileInfo(code,
        fileName, url, source, size, realName, suffix, contentType, request.getFromCode(), md5,request.getFileTypeCode());
    sysFileMapper.addFile(fileInfo, userid);
    DataScriptTypeInfo dataScriptTypeInfo = dataScriptTypeService.getScriptTypeCode(request.getFileTypeCode());
    if(!ObjectUtils.isEmpty(dataScriptTypeInfo)){
        fileInfo.setFileTypeName(dataScriptTypeInfo.getScriptType());
    }

    return fileInfo;
  }

  @Override
  public SysFileInfo getFileByCode(String code) {
    return sysFileMapper.getFileByCode(code);
  }

  @Override
  public List<SysFileInfo> getFilesByFromCode(String fromCode) {
    return sysFileMapper.getFilesByFromCode(fromCode);
  }

  @Override
  public List<SysFileInfo> getFilesByPage(SysFileRequestDTO request) {
    PageHelper.startPage(request.getPageNum(), request.getPageSize());
    return sysFileMapper.getFilesByPage(request);
  }

  @Override
  public void download(String code, HttpServletResponse response)
      throws UnsupportedEncodingException {
    //通过code获取file详情数据
    SysFileInfo fileInfo = getFileByCode(code);
    //下载
    //Handler handler = new Handler();
    //byte[] fileByte = handler.downloadFile(fileInfo.getSource());
    byte[] fileByte = fileToByteArray(fileInfo.getSource());

    response.setHeader(
        "Content-disposition",
        "attachment;filename=" + URLEncoder.encode(fileInfo.getShowName(), "UTF-8"));
    //response.setCharacterEncoding("UTF-8");
    response.setContentType("application/octet-stream");
    try {
      ServletOutputStream servletOutputStream = response.getOutputStream();
      int len;
      byte[] buffer = new byte[1024];
      ByteArrayInputStream is = new ByteArrayInputStream(fileByte);
      while ((len = is.read(buffer)) > 0) {
        servletOutputStream.write(buffer, 0, len);
      }
      servletOutputStream.flush();
      is.close();
      servletOutputStream.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 上传脚本文件，根据脚本类型,上传到aswS3服务器
   *
   * @param request
   * @return
   */
  @Override
  public SysFileInfo uploadScriptType(SysFilesRequestDTO request) throws IOException, URISyntaxException, NoSuchAlgorithmException {
//    List<MultipartFile> files = request.getFiles();
//
//    List<SysFileInfo> sysFileInfos = new ArrayList<>();
//
//    //限制上传文件数量
//    if(files.size() > 10 ){
//      throw new  ServiceException(ErrorCodeConstants.UPLOAD_FILE_NUMBER_CAN_NOT_BEYOND_LIMITATION.getMsg());
//    }
    SysFileRequestDTO sysFileRequestDTO = new SysFileRequestDTO();
    sysFileRequestDTO.setFile(request.getFile());
    sysFileRequestDTO.setFileTypeCode(request.getFileTypeCode());
    SysFileInfo sysFileInfo = this.uploadScript(sysFileRequestDTO, SecurityUtils.getLoginUser().getUserId());

//    for (MultipartFile file : files) {
//
//      sysFileInfos.add(sysFileInfo);
//    }
//    dataScriptTypeService.getScriptTypeByCode()
    return sysFileInfo;
  }

  private static byte[] fileToByteArray(String filePath) {
    byte[] byteArray = null;
    try {
      Path path = Paths.get(filePath);
      byteArray = Files.readAllBytes(path);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return byteArray;
  }
}
